<?php


// 加载图片
function load_jpeg($file_name)
{
    $img = @imagecreatefromjpeg($file_name);

    /* See if it failed */
    if(!$img)
    {
        /* Create a black image */
        $img = imagecreatetruecolor(150, 30);
        $bgc = imagecolorallocate($img, 255, 255, 255);
        $tc  = imagecolorallocate($img, 0, 0, 0);

        imagefilledrectangle($img, 0, 0, 150, 30, $bgc);

        /* Output an error message */
        imagestring($img, 1, 5, 5, 'Error loading ' . $file_name, $tc);
    }

    return $img;
}


// 一步处理函数
function image_one($gd_resource)
{
	// 获取图片属性
	$w 	   = imagesx($gd_resource);
	$h 	   = imagesy($gd_resource);

	$temp  = imagecreatetruecolor($w, $h);
	$black = imagecolorallocate($temp, 0, 0, 0);
	$white = imagecolorallocate($temp, 255, 255, 255);


	
	// 用于记录移除的点
	$flag = ['r'=>0, 'g'=>0, 'b'=>0];
	$num  = 0;
	$postion = [];

	// 纵向过滤点
	for ($i=0; $i<$w; $i++) {

	    for ($j=0; $j<$h; $j++) {

	    	$rgb = getRGB($gd_resource, $i, $j);

	    	// 白色直接跳过
	        if (!isBlack($rgb)) {
	            imagesetpixel($temp, $i, $j, $white);
	            continue;
	        }

	        // 记录数值 >=2 的值
	        $count = 0;
	        $mark  = [];
	        while (isBlack($rgb) && ++$count && $j < $h) {
	        	$mark[] = [$i, $j, $rgb];
	        	$rgb  = getRGB($gd_resource, $i, ++$j);
	        }
	        --$j;

	        // 上色
    		foreach ($mark as $pos) {
    			$color = $black;
    			if ($count <=2 ) {
	    			$color = $white;
	    			$flag['r'] += $pos[2]['r'];
	    			$flag['g'] += $pos[2]['g'];
	    			$flag['b'] += $pos[2]['b'];
	    			$postion[$pos[0].'.'.$pos[1]] = true;
	    			$num++;
    			}
            	imagesetpixel($temp, $pos[0], $pos[1], $color);
    		}

		}
	}


	// 横向过滤点
    for ($j=0; $j<$h; $j++) {

		for ($i=0; $i<$w; $i++) {

	    	$rgb = getRGB($temp, $i, $j);

	    	// 白色直接跳过
	        if (!isBlack($rgb)) {
	            imagesetpixel($temp, $i, $j, $white);
	            continue;
	        }


	        // 记录数值 >=2 的值
	        $count = 0;
	        $mark  = [];
	        while (isBlack($rgb) && ++$count && $i < $w) {
	        	$mark[] = [$i, $j, $rgb];
	        	$rgb  = getRGB($temp, ++$i, $j);
	        }
	        --$i;

	        // 上色
    		foreach ($mark as $pos) {
    			$color = $black;
    			if ($count <=2 ) {
	    			$color = $white;
	    			$flag['r'] += $pos[2]['r'];
	    			$flag['g'] += $pos[2]['g'];
	    			$flag['b'] += $pos[2]['b'];
	    			$postion[$pos[0].'.'.$pos[1]] = true;
	    			$num++;
    			}
            	imagesetpixel($temp, $pos[0], $pos[1], $color);
    		}
	    }
	}

	// 获取平均值,移除容差
	$avg['r'] = $flag['r']/$num;
	$avg['g'] = $flag['g']/$num;
	$avg['b'] = $flag['b']/$num;

	// 去掉相识的颜色
    for ($j=0; $j<$h; $j++) {

		for ($i=0; $i<$w; $i++) {

	    	$rgb = getRGB($gd_resource, $i, $j);

	    	// 颜色相识,或则在已经删除的点的位置
	    	$key = "{$i}.{$j}";
	    	if (array_key_exists($key, $postion) || isLike($rgb, $avg)) {
            	imagesetpixel($temp, $i, $j, $white);
	    	}
	    }
	}

	return $temp;
}


// 获取均值
function img_avg($gd_resource)
{
	$w 	   = imagesx($gd_resource);
	$h 	   = imagesy($gd_resource);

	$temp  = imagecreatetruecolor($w, $h);
	$black = imagecolorallocate($temp, 0, 0, 0);
	$white = imagecolorallocate($temp, 255, 255, 255);


	// 记录平均值,移除相似的值
	$sum  = 0;
	$info = ['r'=>0,'g'=>0,'b'=>0];
	for ($i=0; $i<$w; $i++) {

	    for ($j=0; $j<$h; $j++) {

	    	if ($i < 2 || $j < 2) {
	    		continue;
	    	}

	        $rgb = getRGB($gd_resource, $i, $j);

	        // 是白色,直接跳过
	        if (!isBlack($rgb)) {
	            imagesetpixel($temp, $i, $j, $white);
	            continue;
	        }


	        // 上一个点事黑色的,当前点也是黑色的
	    	$u1 = getRGB($temp, $i, $j-1);
	    	if (isBlack($u1)) {
	            imagesetpixel($temp, $i, $j, $black);
	    		continue;
	    	}


	        // 简单去掉干扰线
	    	$d1 = getRGB($gd_resource, $i, $j+1);
	    	$d2 = getRGB($gd_resource, $i, $j+2);
	    	if (!isBlack($d1)) {
	    		$yes = true;
	    	} elseif (isBlack($d1) && !isBlack($d2)) {
	    		$yes = true;
	    	} else {
	    		$yes = false;
	    	}


	    	if ($yes) {
	    		$info['r'] += $rgb['r'];
	    		$info['g'] += $rgb['g'];
	    		$info['b'] += $rgb['b'];
	    		$sum++;
	    		imagesetpixel($temp, $i, $j, $white);
	    	} else {
	    		imagesetpixel($temp, $i, $j, $black);
	    	}

	    }
	}
	imagedestroy($temp);
	$temp = null;

	$info['sum'] = $sum;

	return $info;
}


// 处理干扰线
function img_line($gd_resource, $info)
{
	$w 	   = imagesx($gd_resource);
	$h 	   = imagesy($gd_resource);

	$temp  = imagecreatetruecolor($w, $h);
	$black = imagecolorallocate($temp, 0, 0, 0);
	$white = imagecolorallocate($temp, 255, 255, 255);

	$avg = [
		'r' => $info['r']/$info['sum'],
		'g' => $info['g']/$info['sum'],
		'b' => $info['b']/$info['sum'],
	];

	for ($i=0; $i<$w; $i++) {

	    for ($j=0; $j<$h; $j++) {

	    	if ($i < 2 || $j < 2) {
	            imagesetpixel($temp, $i, $j, $white);
	    		continue;
	    	}

	        $rgb = getRGB($gd_resource, $i, $j);

	        // 是白色,直接跳过
	        if (!isBlack($rgb)) {
	            imagesetpixel($temp, $i, $j, $white);
	            continue;
	        }

	        // 近似值,直接添加白背景
            imagesetpixel($temp, $i, $j, isLike($rgb, $avg) ? $white : $black);
	    }
	}

	return $temp;
}


// 去噪点
function img_nosie($gd_resource)
{
	$w 	   = imagesx($gd_resource);
	$h 	   = imagesy($gd_resource);

	$temp  = imagecreatetruecolor($w, $h);
	$black = imagecolorallocate($temp, 0, 0, 0);
	$white = imagecolorallocate($temp, 255, 255, 255);


	for ($i=0; $i<$w; $i++) {

	    for ($j=0; $j<$h; $j++) {

	    	if ($i < 2 || $j < 2) {
	            imagesetpixel($temp, $i, $j, $white);
	    		continue;
	    	}

	        $rgb = getRGB($gd_resource, $i, $j);

	        // 是白色,直接跳过
	        if (!isBlack($rgb)) {
	            imagesetpixel($temp, $i, $j, $white);
	            continue;
	        }


	        // 上一个点事黑色的,当前点也是黑色的
	    	$u1 = getRGB($temp, $i, $j-1);
	    	if (isBlack($u1)) {
	            imagesetpixel($temp, $i, $j, $black);
	    		continue;
	    	}


	        // 简单去掉干扰线
	    	$d1 = getRGB($gd_resource, $i, $j+1);
	    	$d2 = getRGB($gd_resource, $i, $j+2);
	    	if (!isBlack($d1)) {
	    		$yes = true;
	    	} elseif (isBlack($d1) && !isBlack($d2)) {
	    		$yes = true;
	    	} else {
	    		$yes = false;
	    	}

	    	if ($yes) {
	            imagesetpixel($temp, $i, $j, $white);
	    	} else {
	            imagesetpixel($temp, $i, $j, $black);
	    	}

		}
	}
	return $temp;
}


// 放大图片
function img_resize($im, $val = 3)  
{  
    $w = imagesx($im);
    $h = imagesy($im);
    $newwidth  = $w * $val;
    $newheight = $h * $val;

    if(function_exists("imagecopyresampled")) {
		$newim = imagecreatetruecolor($newwidth,$newheight);
		imagecopyresampled($newim,$im,0,0,0,0,$newwidth,$newheight,$w,$h);
    } else {
    	$newim = imagecreate($newwidth,$newheight);
		imagecopyresized($newim,$im,0,0,0,0,$newwidth,$newheight,$w,$h);
    }

	return $newim;    
} 


// 图片修正
function img_exec($gd_resource, $num = 2)
{
	$info = img_avg($gd_resource);
	$temp = img_line($gd_resource, $info);
	$temp = img_nosie($temp);
	$temp = img_resize($temp);
	return $temp;
}


// 二值图
function black($path)
{
	$gd_resource = imagecreatefrompng($path);
	$w = imagesx($gd_resource);
	$h = imagesy($gd_resource);

	$canvas= imagecreatetruecolor($w, $h);
	$black = imagecolorallocate($canvas, 0, 0, 0);
	$white = imagecolorallocate($canvas, 255, 255, 255);

	for ($i=0; $i<$w; $i++) {

	    for ($j=0; $j<$h; $j++) {

	    	if (isBlack(getRGB($gd_resource, $i, $j))) {
		    	imagesetpixel($canvas, $i, $j, $black);
	    	} else {
		    	imagesetpixel($canvas, $i, $j, $white);
	    	}

    	}
    }
    
    return $canvas;
}


/**
 * 将字符图片切分成单个字符
 * @param  resource $gd_resource 图片资源
 * @param  integer  $filter      过滤掉小于10个点的块
 * @return yet/return resource
 */
function img_split($gd_resource, $filter = 30)
{
	$w = imagesx($gd_resource);
	$h = imagesy($gd_resource);

	// 遍历所有的点
	$chunk_set = array();

	for ($i=0; $i<$w; $i++) {

	    for ($j=0; $j<$h; $j++) {

	    	// 黑点计算块区域
	    	if (isBlack(getRGB($gd_resource, $i, $j))) {
	    		$chunk  = array();
		    	$offset = img_chunk($gd_resource, $chunk, $i, $j);
		    	if (count($chunk) >= $filter) {
			    	$chunk_set[] = [$chunk, $offset];
		    	}

		    	// 使用偏移量,不需要重新裁剪
		    	$i = $offset[2];
		    	$j = $offset[3];
	    	}

	    }
	}
	
	return $chunk_set;
}


/**
 * 查找资源块
 * @param  resource  $gd_resource 图片资源
 * @param  integer   $x           位置x
 * @param  Array     $point_set   点集合
 * @param  integer   $y           位置y
 * @return Array [minX,minY,maxX,maxY]
 */
function img_chunk(&$gd_resource, Array &$point_set = [], $x=1, $y=1)
{

	$w = imagesx($gd_resource);
	$h = imagesy($gd_resource);
	if ($x<0 || $y<0 || $x>($w-1) || $y>($h-1)) {
		return NULL;
	}

	// 已经统计过这个点了
	$key = "{$x}.{$y}";
	if (@$point_set[$key]) {
		return NULL;
	}

	// 白色跳出
	if (!isBlack(getRGB($gd_resource, $x, $y))) {
		return NULL;
	}

	// 保存当前
	$point_set[$key] = [$x, $y];


	$list_pos = Array();

	// 上
	$list_pos[] = img_chunk($gd_resource, $point_set, $x, $y-1);

	// 上-右
	$list_pos[] = img_chunk($gd_resource, $point_set, $x+1, $y-1);
	
	// 右
	$list_pos[] = img_chunk($gd_resource, $point_set, $x+1, $y);

	// 右-下
	$list_pos[] = img_chunk($gd_resource, $point_set, $x+1, $y+1);

	// 下
	$list_pos[] = img_chunk($gd_resource, $point_set, $x, $y+1);

	// 下-左
	$list_pos[] = img_chunk($gd_resource, $point_set, $x-1, $y+1);

	// 左
	$list_pos[] = img_chunk($gd_resource, $point_set, $x-1, $y);

	// 左-上
	$list_pos[] = img_chunk($gd_resource, $point_set, $x-1, $y-1);


	// 筛选最小的点与最大的点;
	$offset = deepin($list_pos, [$x, $y, $x, $y]);

	// 返回最小偏移点,和最大偏移点
	return $offset;
}


/**
 * 获取颜色值
 *
 * @param  [type] $gd_resource [description]
 * @param  [type] $i           [description]
 * @param  [type] $j           [description]
 * @return [type]              [description]
 */
function getRGB($gd_resource, $i, $j)
{
	$rgb = imagecolorat($gd_resource, $i, $j);
	$r = ($rgb >> 16) & 0xFF;
	$g = ($rgb >> 8) & 0xFF;
	$b = $rgb & 0xFF;
	return ['r'=>$r, 'g'=>$g, 'b'=>$b];
}


/**
 * 是否黑色,通过阀值取点
 * @param  [type]  $rgb [description]
 * @return boolean      [description]
 */
function isBlack($rgb)
{
	static $limit = ['r' => 180, 'g' => 150, 'b' => 256];
	return ($rgb['r'] < $limit['r'] 
        	&& $rgb['g'] < $limit['g'] 
        	&& $rgb['b'] < $limit['b']);
}


function isLike($rgb, $avg, $scalar = 10)
{
	$ret = (abs($rgb['r'] - $avg['r']) < $scalar 
		&& abs($rgb['g'] - $avg['g']) < $scalar 
		&& abs($rgb['b'] - $avg['b']) < $scalar);
	return $ret;
}


/**
 * 获取深度点
 * 
 * @param  Array   $list_pos 目标点
 * @param  Array   $current  当前区域
 * @return Array|null
 */
function deepin(Array $list_pos, Array $current)
{
	list($c_minX, $c_minY, $c_maxX, $c_maxY) = $current;

	foreach ($list_pos as $pos) {

		if (empty($pos)) continue;

		list($p_minX, $p_minY, $p_maxX, $p_maxY) = $pos;

		if ($p_minX < $c_minX) {
			$c_minX = $p_minX;
		}

		if ($p_minY < $c_minY) {
			$c_minY = $p_minY;
		}

		if ($p_maxX > $c_maxX) {
			$c_maxX = $p_maxX;
		}

		if ($p_maxY > $c_maxY) {
			$c_maxY = $p_maxY;
		}

	}

	return [$c_minX, $c_minY, $c_maxX, $c_maxY];
}



/**
 * 图片的点
 * @param  Array  $chunk   [description]
 * @return NULL            [description]
 */
function img_draw(Array $chunk, $name = '1.png')
{
	$list_point = $chunk[0];
	list($minX, $minY, $maxX, $maxY) = $chunk[1];
	
	$w = $maxX - $minX + 1;
	$h = $maxY - $minY + 1;
	$canvas= imagecreatetruecolor($w, $h);
	$black = imagecolorallocate($canvas, 0, 0, 0);
	$white = imagecolorallocate($canvas, 255, 255, 255);

	for ($i=0; $i<$w; $i++) {

	    for ($j=0; $j<$h; $j++) {
	    	
	    	$pos_i = $i + $minX;
	    	$pos_j = $j + $minY;
	    	$key = "{$pos_i}.{$pos_j}";
	    	if (array_key_exists($key, $list_point)) {
		    	imagesetpixel($canvas, $i, $j, $black);
	    	} else {
		    	imagesetpixel($canvas, $i, $j, $white);
	    	}

    	}
    }

    imagepng($canvas, $name);
    imagedestroy($canvas);
}